package cn.francis.config;

import cn.francis.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Name: SecurityConfig
 * Package: cn.francis.config
 * Date: 2024/10/24 - 10:22
 * Description:
 *
 * @author Junhui Zhang
 * @version v1.0
 */

@Configuration
public class SecurityConfig {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;
    /**
     * 安全过滤器链
     * @param httpSecurity Http请求授权
     * @return 安全过滤器链
     * @throws Exception 异常
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                       .csrf().disable()
                       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                       .and()
                       .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                       .exceptionHandling()
                       .authenticationEntryPoint(authenticationEntryPoint)
                       .accessDeniedHandler(accessDeniedHandler)
                       .and()
                       .headers()
                       .frameOptions().disable()
                       .and()
                       .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> {
                           authorizationManagerRequestMatcherRegistry
                                   .antMatchers("/sys/user/login", "/backend/**").permitAll()
                                   .anyRequest().authenticated();
                       }).build();
    }

    /**
     * 密码编码器
     * @return 密码编码器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 认证管理器
     * @param authenticationConfiguration 配置
     * @return 认证管理器
     * @throws Exception 异常
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}
